﻿using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.IO;
using System.Text;

namespace Mrc.Common.Helpers
{
    public class RsaEncryHelper
    {
        public static void test()
        {
           var keyinfo= GenRSAKeyPair("xman");
           string encryptedTxt = RsaEncryptWithPublic(keyinfo.PublicKey,new{ Name = "喷射战士2haha" });
           var decryText=RsaDecryptWithPrivate(keyinfo.PrivateKey,encryptedTxt);
           var t= RsaEncryptWithPrivate(keyinfo.PrivateKey,new{Name="odessey"});
           var t2=RsaDecryptWithPublic(keyinfo.PublicKey,t);
        }



        public static RsaKeyModel GenRSAKeyPair(string name)
        {
            RsaKeyModel result = new RsaKeyModel();
            var generator = new RsaKeyPairGenerator();
            var seed = Encoding.UTF8.GetBytes(name);
            var secureRandom = new SecureRandom();
            secureRandom.SetSeed(seed);
            generator.Init(new KeyGenerationParameters(secureRandom, 4096));
            var pair = generator.GenerateKeyPair();

            //私钥
            var twPrivate = new StringWriter();
            PemWriter pwPrivate = new PemWriter(twPrivate);
            pwPrivate.WriteObject(pair.Private);
            pwPrivate.Writer.Flush();
            result.PrivateKey = twPrivate.ToString();
 
            //公钥
            var twPublic = new StringWriter();
            PemWriter pwPublic = new PemWriter(twPublic);
            pwPublic.WriteObject(pair.Public);
            pwPublic.Writer.Flush();
            result.PublicKey = twPublic.ToString();

            return result;
        }

        /// <summary>
        /// 公钥加密
        /// </summary>
        /// <param name="dataToEncrypt">待加密文本</param>
        //public static void RsaEncryptWithPublic(string dataToEncrypt)
        public static string RsaEncryptWithPublic(string publicKey, object dataToEncrypt)
        {
            var bytesToEncrypt = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dataToEncrypt));
            var encryptEngine = new Pkcs1Encoding(new RsaEngine());
            using (var txtReader = new StringReader(publicKey))
            {
                var keyParameter = (AsymmetricKeyParameter)new PemReader(txtReader).ReadObject();
                encryptEngine.Init(true, keyParameter);
            }
            var encryptedText = Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
            Console.WriteLine("利用公钥加密后的数据：" + encryptedText);
            return encryptedText;
        }

        /// <summary>
        /// 私钥加密
        /// </summary>
        /// <param name="dataToEncrypt">待加密文本</param>
        //public static void RsaEncryptWithPrivate(string dataToEncrypt)
        public static string RsaEncryptWithPrivate(string privateKey, object dataToEncrypt)
        {
            var bytesToEncrypt = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dataToEncrypt));
            var encryptEngine = new Pkcs1Encoding(new RsaEngine());
            using (var txtReader = new StringReader(privateKey))
            {
                var keyPair = (AsymmetricCipherKeyPair)new PemReader(txtReader).ReadObject();
                encryptEngine.Init(true, keyPair.Private);
            }
           return Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
            
        }


        /// <summary>
        /// 私钥解密
        /// </summary>
        /// <param name="dataToDecrypt">待解密的数据</param>
        public static string RsaDecryptWithPrivate(string privateKey, string dataToDecrypt)
        {
            var bytesToDecrypt = Convert.FromBase64String(dataToDecrypt);
            var stringReader = new StringReader(privateKey);
            var pemReader = new PemReader(stringReader);
            var keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
            var keyParameter = keyPair.Private;
            // 用私钥解密的第二种方法
            IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
            cipher.Init(false, keyParameter);
            var decipheredBytes = cipher.DoFinal(bytesToDecrypt);
            return Encoding.UTF8.GetString(decipheredBytes);
        }

        /// <summary>
        /// 公钥解密
        /// </summary>
        /// <param name="dataToDecrypt">待解密的数据</param>
        public static string RsaDecryptWithPublic(string publicKey, string dataToDecrypt)
        {
            var bytesToDecrypt = Convert.FromBase64String(dataToDecrypt);
            var stringReader = new StringReader(publicKey);
            var pemReader = new PemReader(stringReader);
            var keyParameter = (AsymmetricKeyParameter)pemReader.ReadObject();
            IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
            cipher.Init(false, keyParameter);
            var decipheredBytes = cipher.DoFinal(bytesToDecrypt);
            return Encoding.UTF8.GetString(decipheredBytes);
          
        }
    }

    public class RsaKeyModel
    {
        /// <summary>
        /// 公钥
        /// </summary>
        public string PublicKey { get; set; }
        /// <summary>
        /// 私钥
        /// </summary>
        public string PrivateKey { get; set; }


    }
}